package sk.tramtatiri.pages.users;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
import org.apache.wicket.ajax.markup.html.form.AjaxButton;
import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.CheckBox;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.TextArea;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.markup.html.panel.FeedbackPanel;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.Model;
import org.apache.wicket.spring.injection.annot.SpringBean;

import sk.tramtatiri.MySession;
import sk.tramtatiri.core.FoundFood;
import sk.tramtatiri.core.Ingredient;
import sk.tramtatiri.data.dao.interfaces.FoodDao;
import sk.tramtatiri.data.dao.interfaces.InOutHelperDao;
import sk.tramtatiri.data.dao.interfaces.RecipeDao;
import sk.tramtatiri.data.dao.interfaces.UserDao;
import sk.tramtatiri.data.dao.interfaces.UserFoodDao;
import sk.tramtatiri.data.dao.interfaces.UserRecipeDao;
import sk.tramtatiri.data.dataobjects.Food;
import sk.tramtatiri.data.dataobjects.InOutHelper;
import sk.tramtatiri.data.dataobjects.Recipe;
import sk.tramtatiri.data.dataobjects.UserRecipe;

public class RecipeCreateModal extends Panel {

	private static final long serialVersionUID = -150565538135748803L;

	@SpringBean
	private FoodDao foodDao;
	@SpringBean
	private RecipeDao recipeDao;
	@SpringBean
	private UserRecipeDao userRecipeDao;
	@SpringBean
	private UserDao userDao;
	@SpringBean
	private InOutHelperDao inOutHelperDao;
	@SpringBean
	private UserFoodDao userFoodDao;
	
	//mena nenajdenych potravin
	List<Label> notFoundFoodsLabels = new ArrayList<Label>();
	//hodnoty nenajdenych jedal
	List<TextField> notFoundFoodsTextFields = new ArrayList<TextField>();
	//hodnoty najdenych potravin okrem hmotnosti
	List<Label> foundFoodsLabels = new ArrayList<Label>();
	//hmotnosti najdenych jedal
	List<TextField> foundFoodsTextFields = new ArrayList<TextField>();
	
	public RecipeCreateModal(String id, final ModalWindow modal,
			final List<FoundFood> foundFoods, List<Ingredient> notFoundFoods, final String recipeName, String recipeProcedure) {
		super(id);

		FeedbackPanel feedback = new FeedbackPanel("feedback");
		feedback.setOutputMarkupId(true);
		add(feedback);
		
		Calendar cal0 = Calendar.getInstance();
		cal0.set(cal0.get(Calendar.YEAR), cal0.get(Calendar.MONTH),
				cal0.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
		final Date today0 = new Date(cal0.getTimeInMillis());
		
		final Form<?> form = new Form<Void>("formRecipeCreateModal");

		form.add(new ListView<Ingredient>("row", notFoundFoods) {

			private static final long serialVersionUID = 1290338125516294122L;

			@Override
			protected void populateItem(final ListItem<Ingredient> item) {
				final Ingredient ingredient = (Ingredient) item.getModelObject();

				Label label = new Label("name", Model.of(ingredient.getName()));
				label.setOutputMarkupId(true);
				item.add(label);
				notFoundFoodsLabels.add(label);

				TextField textField = new TextField<Integer>("totalCalories", Model.of(0));
				textField.setOutputMarkupId(true);
				textField.add(new AjaxFormComponentUpdatingBehavior("onKeyUp"){

					private static final long serialVersionUID = 1L;

					@Override
					protected void onUpdate(AjaxRequestTarget target) {
						String calories = item.get("totalCalories").getDefaultModelObjectAsString();
						if(calories.matches("\\d+")){
							refreshTotalCalories(form, target);
						}
					}
				});
				item.add(textField);
				notFoundFoodsTextFields.add(textField);

				textField = new TextField<Integer>("saccharides", Model.of(0));
				textField.setOutputMarkupId(true);
				textField.add(new AjaxFormComponentUpdatingBehavior("onKeyUp"){

					private static final long serialVersionUID = -6461336953532111116L;

					@Override
					protected void onUpdate(AjaxRequestTarget target) {
						String saccharides = item.get("saccharides").getDefaultModelObjectAsString();
						if(saccharides.matches("\\d+")){
							refreshTotalSaccharides(form, target);
						}
					}
				});
				item.add(textField);
				notFoundFoodsTextFields.add(textField);

				textField = new TextField<Integer>("fats", Model.of(0));
				textField.setOutputMarkupId(true);
				textField.add(new AjaxFormComponentUpdatingBehavior("onKeyUp"){

					private static final long serialVersionUID = 2203875563660544705L;

					@Override
					protected void onUpdate(AjaxRequestTarget target) {
						String fats = item.get("fats").getDefaultModelObjectAsString();
						if(fats.matches("\\d+")){
							refreshTotalFats(form, target);
						}
					}
				});
				item.add(textField);
				notFoundFoodsTextFields.add(textField);

				textField = new TextField<Integer>("proteins", Model.of(0));
				textField.setOutputMarkupId(true);
				textField.add(new AjaxFormComponentUpdatingBehavior("onKeyUp"){

					private static final long serialVersionUID = 6380342620626389199L;

					@Override
					protected void onUpdate(AjaxRequestTarget target) {
						String proteins = item.get("proteins").getDefaultModelObjectAsString();
						if(proteins.matches("\\d+")){
							refreshTotalProteins(form, target);
						}
					}
				});
				item.add(textField);
				notFoundFoodsTextFields.add(textField);

				textField = new TextField<String>("weight", Model.of(ingredient.getWeight() + ""));
				textField.setOutputMarkupId(true);
				textField.add(new AjaxFormComponentUpdatingBehavior("onKeyUp"){

					private static final long serialVersionUID = 4095835299525918020L;

					@Override
					protected void onUpdate(AjaxRequestTarget target) {
						String weight = item.get("weight").getDefaultModelObjectAsString();
						if(weight.matches("\\d+")){
							refreshTotalWeight(form, target);
						}
					}
				});
				item.add(textField);
				notFoundFoodsTextFields.add(textField);
			}
		}.setOutputMarkupId(true));
		
		form.add(new ListView<FoundFood>("row_founded", foundFoods) {

			private static final long serialVersionUID = 1290338125516294122L;

			@Override
			protected void populateItem(final ListItem<FoundFood> item) {
				final FoundFood foundFood = (FoundFood) item.getModelObject();
				final Food food = foundFood.getFood();

				// mozno to pojde do metody, koli meneniu hodnot po zadani inej
				// hmotnosti
				float times = Float.valueOf(foundFood.getWeight()) / 100;
				int calories = Math.round(food.getCalories() * times);
				int fats = Math.round(food.getFats() * times);
				int proteins = Math.round(food.getProteins() * times);
				int saccharides = Math.round(food.getSaccharides() * times);

				item.add(new Label("f_name", food.getName()));
				
				Label label = new Label("f_calories", calories + "");
				label.setOutputMarkupId(true);
				item.add(label);
				foundFoodsLabels.add(label);
				
				label = new Label("f_saccharides", saccharides + "");
				label.setOutputMarkupId(true);
				item.add(label);
				foundFoodsLabels.add(label);
				
				label = new Label("f_fats", fats + "");
				label.setOutputMarkupId(true);
				item.add(label);
				foundFoodsLabels.add(label);
				
				label = new Label("f_proteins", proteins + "");
				label.setOutputMarkupId(true);
				item.add(label);
				foundFoodsLabels.add(label);
				
				TextField textField = new TextField<String>("f_weight", Model.of(foundFood.getWeight() + ""));
				textField.setOutputMarkupId(true);
				textField.add(new AjaxFormComponentUpdatingBehavior("onKeyUp"){

					private static final long serialVersionUID = 8535991910938912331L;

					@Override
					protected void onUpdate(AjaxRequestTarget target) {
						int calories = 0;
						int fats = 0;
						int proteins = 0;
						int saccharides = 0;
						String weight = item.get("f_weight").getDefaultModelObjectAsString();
						if(weight.matches("\\d+")){
							Food food = foundFood.getFood();
							float times = Float.valueOf(weight)/100;
						
							calories = Math.round(food.getCalories() * times);
							fats = Math.round(food.getFats() * times);
							proteins = Math.round(food.getProteins() * times);
							saccharides = Math.round(food.getSaccharides() * times);
						}
						
						target.addComponent(item.get("f_calories").setDefaultModelObject(calories));
						target.addComponent(item.get("f_saccharides").setDefaultModelObject(saccharides));
					    target.addComponent(item.get("f_fats").setDefaultModelObject(fats));
						target.addComponent(item.get("f_proteins").setDefaultModelObject(proteins));
						
						if(weight.matches("\\d+")){
							refreshTotalValues(form, target);
						}
					}
				});
				item.add(textField);
				foundFoodsTextFields.add(textField);
			}
		}.setReuseItems(true).setOutputMarkupId(true));
		
		
		int totalCalories = 0;
		int totalSaccharides = 0;
		int totalFats = 0;
		int totalProteins = 0;
		int totalWeight = 0;
		
		for (FoundFood foundFood : foundFoods) {
			Food food = foundFood.getFood();
			int weight = foundFood.getWeight();
			totalCalories = totalCalories + Math.round((food.getCalories() * weight) / 100);
			totalSaccharides = totalSaccharides + Math.round((food.getSaccharides() * weight) / 100);
			totalFats = totalFats + Math.round((food.getFats() * weight) / 100);
			totalProteins = totalProteins + Math.round((food.getProteins() * weight) / 100);
			totalWeight = totalWeight + weight;
		}
		for (Ingredient ingredient : notFoundFoods) {
			totalWeight = totalWeight + ingredient.getWeight();
		}
		
		form.add(new Label("all_calories", totalCalories+"").setOutputMarkupId(true));
		form.add(new Label("all_saccharides", totalSaccharides+"").setOutputMarkupId(true));
		form.add(new Label("all_fats", totalFats+"").setOutputMarkupId(true));
		form.add(new Label("all_proteins", totalProteins+"").setOutputMarkupId(true));
		form.add(new Label("all_weight", totalWeight+"").setOutputMarkupId(true));
		
		form.add(new TextArea("recipeProcedure", Model.of(recipeProcedure)).setOutputMarkupId(true));
		
		form.add(new CheckBox("recipeCheck", new Model<Boolean>(true)));

		form.add(new AjaxButton("create_closeModal") {

			private static final long serialVersionUID = -6045664155196198289L;

			@Override
			protected void onSubmit(AjaxRequestTarget target, Form<?> arg1) {
				long creatorID = ((MySession)getSession()).getUserID();
				if(checkNotFoundFoodsLabels()){
					if(checkFoundFoodsTextFields()){
						if(checkNotFoundFoodsTextFields()){
							Recipe recipe = new Recipe();
							recipe.setRating(0);
							recipe.setCalories(Integer.valueOf(form.get("all_calories").getDefaultModelObjectAsString()));
							recipe.setSaccharides(Integer.valueOf(form.get("all_saccharides").getDefaultModelObjectAsString()));
							recipe.setFats(Integer.valueOf(form.get("all_fats").getDefaultModelObjectAsString()));
							recipe.setProteins(Integer.valueOf(form.get("all_proteins").getDefaultModelObjectAsString()));
							recipe.setName(recipeName);
							recipe.setCreatorID(creatorID);
							recipe.setPortion(Math.round(Float.valueOf(form.get("all_proteins").getDefaultModelObjectAsString())/330));
							recipe.setDescription(form.get("recipeProcedure").getDefaultModelObjectAsString());
					
							String[] ingredients = new String[notFoundFoodsLabels.size() + foundFoods.size()];
							int[] weights = new int[notFoundFoodsLabels.size() + foundFoods.size()];
							int i = 0;
							for (Label label : notFoundFoodsLabels) {
								ingredients[i] = label.getDefaultModelObjectAsString();
								weights[i] = Integer.valueOf(notFoundFoodsTextFields.get(i*5+4).getValue());
								i++;
							}
							int j = 0;
							for (FoundFood foundFood : foundFoods) {
								ingredients[i] = foundFood.getFood().getName();
								weights[i] = Integer.valueOf(foundFoodsTextFields.get(j).getValue());
								i++;
								j++;
							}
							recipe.setIngredients(ingredients);
							recipe.setWeights(weights);
							boolean isAllValues = true;
					
							for (i = 0; i < notFoundFoodsTextFields.size(); i = i + 5) {
								Food food = new Food();
								boolean isAllFoodValues = true;
								int calories = Integer.valueOf(notFoundFoodsTextFields.get(i).getValue());
								int saccharides = Integer.valueOf(notFoundFoodsTextFields.get(i+1).getValue());
								int fats = Integer.valueOf(notFoundFoodsTextFields.get(i+2).getValue());
								int proteins = Integer.valueOf(notFoundFoodsTextFields.get(i+3).getValue());
								int weight = Integer.valueOf(notFoundFoodsTextFields.get(i+4).getValue());
								if(calories == 0 || saccharides == 0 || fats == 0 || proteins == 0){
									isAllValues = false;
									isAllFoodValues = false;
								}
								String name = notFoundFoodsLabels.get(((int)i/5)).getDefaultModelObjectAsString();
								food.setName(name);
								food.setRating(0);
								food.setCreatorID(creatorID);
								food.setAllValues(isAllFoodValues);
								if(weight == 0){
									calories = 0;
									saccharides = 0;
									fats = 0;
									proteins = 0;
								}else{
									calories = Math.round(Float.valueOf(calories)*100/weight);
									saccharides = Math.round(Float.valueOf(saccharides)*100/weight);
									fats = Math.round(Float.valueOf(fats)*100/weight);
									proteins = Math.round(Float.valueOf(proteins)*100/weight);
								}
								food.setCalories(calories);
								food.setFats(fats);
								food.setProteins(proteins);
								food.setSaccharides(saccharides);
								
								foodDao.save(food);
							}
							recipe.setAllValues(isAllValues);
							recipeDao.save(recipe);
							
							CheckBox box = (CheckBox)form.get("recipeCheck");
							if((Boolean) box.getDefaultModelObject()){
								UserRecipe userRecipe = new UserRecipe();
								
								Calendar cal = Calendar.getInstance();
								cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH),
										cal.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
								
								userRecipe.setDate(new Date(cal.getTimeInMillis()));
								userRecipe.setUser(userDao.load(((MySession) getSession())
										.getUserID()));
								userRecipe.setUserId(((MySession) getSession())
										.getUserID());
								//TODO WTF
								userRecipe.setDayTime(0);
								userRecipe.setTotalCalories(recipe.getCalories());
								userRecipe.setRecipe(recipe);
								long idRecipe = recipeDao.findName(recipeName).getId();
								userRecipe.setRecipeId(idRecipe);
								userRecipeDao.save(userRecipe);
								
								int totalTodayRec = userRecipeDao.sumUserToday(((MySession)getSession()).getUserID());
								int totalTodayFood = userFoodDao.sumUserToday(((MySession)getSession()).getUserID());
								InOutHelper todayHelper = inOutHelperDao.findByUserToday(((MySession)getSession()).getUserID());
								if(todayHelper!=null)
									todayHelper.setCaloriesIn(totalTodayRec+totalTodayFood);
								else {
									InOutHelper newHelper = new InOutHelper();
									newHelper.setDate(today0);
									newHelper.setCaloriesIn(totalTodayRec+totalTodayFood);
									newHelper.setUsrid(((MySession)getSession()).getUserID());
									inOutHelperDao.save(newHelper);
								}
								
								userDao.load(((MySession) getSession()).getUserID())
										.getRecipes().add(userRecipe);
								recipe.getUsers().add(userRecipe);
							}	
							modal.close(target);
						}else{
							//TODO zle zadane hodnoty pre nenajdene jedla
						}
					}else{
						//TODO zle zadana vaha pre najdene jedla
					}
				}else {
					//TODO zle zadany nazov pre nenajdene jedla
				}
			}
		});

		form.add(new AjaxButton("closeModal") {

			private static final long serialVersionUID = -6045664155196198289L;

			@Override
			protected void onSubmit(AjaxRequestTarget target, Form<?> arg1) {
				modal.close(target);
			}
		});

		add(form);
	}
	
	private void refreshTotalCalories(Form form, AjaxRequestTarget target) {
		try{
			int calories = 0;
		
			for (int i = 0; i < notFoundFoodsTextFields.size(); i = i + 5) {
				calories = calories + Integer.valueOf(notFoundFoodsTextFields.get(i).getValue());
			}	
			for (int i = 0; i < foundFoodsLabels.size(); i = i + 4) {
				calories = calories + Integer.valueOf(foundFoodsLabels.get(i).getDefaultModelObjectAsString());
			}	
			target.addComponent(form.get("all_calories").setDefaultModelObject(calories));
		}catch(Exception e){
//			System.out.println("ERROR - Wrong inputs!!!");
			error("Zle zadane hodnoty");
		}
	}
	
	private void refreshTotalSaccharides(Form form, AjaxRequestTarget target) {
		try{
			int saccharides = 0;
		
			for (int i = 0; i < notFoundFoodsTextFields.size(); i = i + 5) {
				saccharides = saccharides + Integer.valueOf(notFoundFoodsTextFields.get(i+1).getValue());
			}
			for (int i = 0; i < foundFoodsLabels.size(); i = i + 4) {
				saccharides = saccharides + Integer.valueOf(foundFoodsLabels.get(i+1).getDefaultModelObjectAsString());
			}
			target.addComponent(form.get("all_saccharides").setDefaultModelObject(saccharides));
		}catch(Exception e){
//			System.out.println("ERROR - Wrong inputs!!!");
			error("Zle zadane hodnoty");
		}
	}
	
	private void refreshTotalFats(Form form, AjaxRequestTarget target) {
		try{
			int fats = 0;

			for (int i = 0; i < notFoundFoodsTextFields.size(); i = i + 5) {
				fats = fats + Integer.valueOf(notFoundFoodsTextFields.get(i+2).getValue());
			}
			for (int i = 0; i < foundFoodsLabels.size(); i = i + 4) {
				fats = fats + Integer.valueOf(foundFoodsLabels.get(i+2).getDefaultModelObjectAsString());
			}
			target.addComponent(form.get("all_fats").setDefaultModelObject(fats));
		}catch(Exception e){
//			System.out.println("ERROR - Wrong inputs!!!");
			error("Zle zadane hodnoty");
		}
	}
	
	private void refreshTotalProteins(Form form, AjaxRequestTarget target) {
		try{
			int proteins = 0;

			for (int i = 0; i < notFoundFoodsTextFields.size(); i = i + 5) {
				proteins = proteins + Integer.valueOf(notFoundFoodsTextFields.get(i+3).getValue());
			}
			for (int i = 0; i < foundFoodsLabels.size(); i = i + 4) {
				proteins = proteins + Integer.valueOf(foundFoodsLabels.get(i+3).getDefaultModelObjectAsString());
			}
			target.addComponent(form.get("all_proteins").setDefaultModelObject(proteins));
		}catch(Exception e){
//			System.out.println("ERROR - Wrong inputs!!!");
			error("Zle zadane hodnoty");
		}
	}
	
	private void refreshTotalWeight(Form form, AjaxRequestTarget target) {
		try{
			int weight = 0;

			for (int i = 0; i < notFoundFoodsTextFields.size(); i = i + 5) {
				weight = weight + Integer.valueOf(notFoundFoodsTextFields.get(i+4).getValue());
			}
			for(int i = 0; i < foundFoodsTextFields.size(); i++){
				weight = weight + Integer.valueOf(foundFoodsTextFields.get(i).getValue());
			}
			target.addComponent(form.get("all_weight").setDefaultModelObject(weight));
		}catch(Exception e){
//			System.out.println("ERROR - Wrong inputs!!!");
			error("Zle zadane hodnoty");
		}
	}
	
	private void refreshTotalValues(Form form, AjaxRequestTarget target) {
		try{
			int calories = 0;
			int saccharides = 0;
			int fats = 0;
			int proteins = 0;
			int weight = 0;
		
			//notFoundFoods
			for (int i = 0; i < notFoundFoodsTextFields.size(); i = i + 5) {
				calories = calories + Integer.valueOf(notFoundFoodsTextFields.get(i).getValue());
				saccharides = saccharides + Integer.valueOf(notFoundFoodsTextFields.get(i+1).getValue());
				fats = fats + Integer.valueOf(notFoundFoodsTextFields.get(i+2).getValue());
				proteins = proteins + Integer.valueOf(notFoundFoodsTextFields.get(i+3).getValue());
				weight = weight + Integer.valueOf(notFoundFoodsTextFields.get(i+4).getValue());
			}
		
			//foundFoods - weight
			for(int i = 0; i < foundFoodsTextFields.size(); i++){
				weight = weight + Integer.valueOf(foundFoodsTextFields.get(i).getValue());
			}
		
			//foundFoods - other values
			for (int i = 0; i < foundFoodsLabels.size(); i = i + 4) {
				calories = calories + Integer.valueOf(foundFoodsLabels.get(i).getDefaultModelObjectAsString());
				saccharides = saccharides + Integer.valueOf(foundFoodsLabels.get(i+1).getDefaultModelObjectAsString());
				fats = fats + Integer.valueOf(foundFoodsLabels.get(i+2).getDefaultModelObjectAsString());
				proteins = proteins + Integer.valueOf(foundFoodsLabels.get(i+3).getDefaultModelObjectAsString());
			}
		
			target.addComponent(form.get("all_calories").setDefaultModelObject(calories));
			target.addComponent(form.get("all_saccharides").setDefaultModelObject(saccharides));
			target.addComponent(form.get("all_fats").setDefaultModelObject(fats));
			target.addComponent(form.get("all_proteins").setDefaultModelObject(proteins));
			target.addComponent(form.get("all_weight").setDefaultModelObject(weight));
		}catch(Exception e){
//			System.out.println("ERROR - Wrong inputs!!!");
			error("Zle zadane hodnoty");
		}
	}
	
	private boolean checkNotFoundFoodsLabels(){
		for (Label label : notFoundFoodsLabels) {
			if(label.getDefaultModelObjectAsString().isEmpty()){
				return false;
			}
		}
		return true;
	}
	
	private boolean checkFoundFoodsTextFields(){
		for (TextField textField : foundFoodsTextFields) {
			if(textField.getValue().isEmpty() || !textField.getValue().matches("\\d+") || textField.getValue().equals("0")){
				return false;
			}
		}
		return true;
	}
	
	private boolean checkNotFoundFoodsTextFields(){
		for (int i = 0; i < notFoundFoodsTextFields.size(); i = i + 5) {
			String calories = notFoundFoodsTextFields.get(i).getValue();
			String saccharides = notFoundFoodsTextFields.get(i+1).getValue();
			String fats = notFoundFoodsTextFields.get(i+2).getValue();
			String proteins = notFoundFoodsTextFields.get(i+3).getValue();
			String weight = notFoundFoodsTextFields.get(i+4).getValue();
			if(calories.isEmpty() || !calories.matches("\\d+")){
				return false;
			}
			if(saccharides.isEmpty() || !saccharides.matches("\\d+")){
				return false;
			}
			if(fats.isEmpty() || !fats.matches("\\d+")){
				return false;
			}
			if(proteins.isEmpty() || !proteins.matches("\\d+")){
				return false;
			}
			if(weight.isEmpty() || !weight.matches("\\d+")){
				return false;
			}
		}
		return true;
	}
}